package com.example.base.filewatch;

import com.example.base.config.BaseSystemInitConfig;
import com.example.base.springboot.DynamicLoad;
import com.example.base.util.URLClassLoaderUtils;
import com.example.base.system.SysAppService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;

@Slf4j
@Component
public class SystemApplicationRunner implements ApplicationRunner {

    @Value("${watch.path}")
    private String watchPath;

    @Autowired
    private DynamicLoad dynamicLoad;

    @Autowired
    private SysAppService sysAppService;

    @Autowired
    private BaseSystemInitConfig baseSystemInitConfig;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        baseSystemInitConfig.loadConfig();
        URLClassLoaderUtils.init(this.getClass().getClassLoader());
        String path=sysAppService.getAppPath();
        final File file = new File(path);
        firstLoadJar(file);
        try {
            new Thread(() -> {
                if(!file.exists()){
                    log.info("文件{}不存在",file.getPath());
                    file.mkdirs();
                    watchDirectoryPath(file.toPath());
                }else {
                    watchDirectoryPath(file.toPath());
                }
            }).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("正在监视文件夹:" + file.getAbsolutePath());
    }

    private void firstLoadJar(File file){
        if(file.exists() && file.isDirectory()){
            File[] files=file.listFiles();
            for (int i = 0; i < files.length ; i++) {
                File f=files[i];
                loadJar(f);
            }
        }
    }

    private void loadJar(File file){
        dynamicLoad.loadJar(file);
    }

    // 在指定的文件夹上启动监听
    private void watchDirectoryPath(Path path) {
        try {
            // 获取文件夹的WatchService实例
            WatchService watchService = FileSystems.getDefault().newWatchService();

            // 注册所关注的事件类型，这里我们关注文件创建、删除和修改事件
            path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
                    StandardWatchEventKinds.ENTRY_DELETE,
                    StandardWatchEventKinds.ENTRY_MODIFY);

            // 启动无限循环来监听文件夹变化
            while (true) {
                WatchKey key;
                try {
                    key = watchService.take();
                } catch (InterruptedException ex) {
                    return;
                }


                // 处理触发的事件
                for (WatchEvent<?> event : key.pollEvents()) {
                    WatchEvent.Kind<?> kind = event.kind();

                    // 通过WatchEvent的上下文来获取文件名
                    @SuppressWarnings("unchecked")
                    WatchEvent<Path> ev = (WatchEvent<Path>) event;
                    Path fileName = ev.context();


                    if("ENTRY_MODIFY".equals(kind.toString()) || "ENTRY_CREATE".equals(kind.toString())){
                        log.info(fileName.toString()+" "+kind.toString());
                        File file=new File(path.toFile().getPath()+File.separator+fileName.toString());
                        Boolean b=WatchFileUtils.isLoadFile(file);
                        if(b){
                            try {
                                loadJar(file);
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                    }
                }

                // 重置WatchKey以接收后续事件
                boolean valid = key.reset();
                if (!valid) {
                    break;
                }
            }

        } catch (IOException ex) {
            System.err.println(ex);
        }
    }
}
